package com.lwlk.util.rubbish.havefun;

import com.lwlk.util.flow.Try;
import com.lwlk.util.functional.Action1;
import com.lwlk.util.functional.Produce;
import com.lwlk.util.string.Lines;
import javax.swing.*;
import java.lang.reflect.Field;
import java.util.*;

import java.util.stream.Stream;

import static com.lwlk.util.functional.Common.returnThat;

public class WTF {

    private static <T> String[] classChain(T var, List<String> classes) {

        if(var == null || classes.contains(var.getClass().getName())) return classes.toArray(new String[classes.size()]);

        else return classChain(var.getClass().getSuperclass(), classes.add(var.getClass().getName()) ? classes : classes);
    }

    public static <T> String[] itClasses(T var) {

        return classChain(var, new ArrayList<>());
    }

    public static <T> String[] itInterfaces(T var) {

        Stream<String> classStream = Stream.of(itClasses(var));

        Stream<Class<?>> interfaceStream = classStream.flatMap((name) ->
                Stream.of(Try.ignoreGet(() -> Class.forName(name).getClass().getInterfaces()).orElse(new Class<?>[0])));

        return interfaceStream.map(Class::getName).toArray(String[]::new);
    }

    public static void main(String[] args) {

        System.out.println(Arrays.toString(WTF.itClasses(new JButton())));

        // System.out.println(Arrays.toString(WTF.itInterfaces(new JButton())));

        // P(oriex(new IllegalArgumentException("Woooooooooo Coooooooool")));
    }

    public static String oriex(Throwable ex) {

        String exname = ex.getClass().getName();

        Field field = withConfig(() -> Throwable.class.getDeclaredField("detailMessage"), (Field f) -> f.setAccessible(true));

        String exmsg = Try.ignoreGet(() -> field.get(ex).toString()).orElse("");

        return new Lines(exname, exmsg).with("(", " : ", ")").content();
    }

    public static <T> T withConfig(Produce<T> builder, Action1<T>... procedures) {

        T source = Try.ignoreGet(builder).orElse(null);

        return source == null ?
                null :
                returnThat(() -> Stream.of(procedures).forEach((p) -> Try.ignoreWith(() -> p.call(source))), source);
    }

    public static void P(Object ... objs) {

        String temp = new Lines(Stream.of(objs).map(Object::toString).toArray(String[]::new)).with("\n").content();

        System.out.println(temp);
    }
}

